﻿using Cemit.Awaiter;
using Cemit.PolyProto;
using Google.Protobuf;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using Microsoft.Extensions.DependencyInjection;
using Cemit.NetFramework.Logger;
using Debug = Cemit.NetFramework.Logger.Debug;

namespace Cemit.NetFramework
{
    /// <summary>
    /// PolyNetwork框架的主类
    /// </summary>
    public static partial class PolyNetwork
    {
        // --- 常量 --- ---
        /// <summary>版本号</summary>
        const string VERSION = "0.1.10";
        /// <summary>在同一帧中最大消息处理量</summary>
        const int MAX_MESSAGE_FIRE = 10;
        // --- --- ---

        // --- 事件 --- ---
        [Obsolete("直接使用await获取等待")]
        public static event Action OnConnectionSucceeded;
        [Obsolete("直接使用await获取等待")]
        public static event Action<string> OnConnectionFailed;
        [Obsolete("未完成")]
        public static event Action OnClosed;
        // --- --- ---

        // --- 属性 --- ---
        /// <summary>用于PolyNetwork运行的设置</summary>
        public static PolyServerSettings Settings { get; set; }
            = ScriptableObject.CreateInstance<PolyServerSettings>();
        /// <summary>使函数委托至Unity主线程中执行</summary>
        public static MonoHandler MonoHandle { get; }
        /// <summary>获取客户端到服务器的双向延迟</summary>
        public static float Ping => IsConnected ? m_MainSocket.GetPing() : -1;
        /// <summary>服务器是否连接</summary>
        public static bool IsConnected => m_MainSocket != null && m_MainSocket.IsConnected;
        /// <summary>获取Ping刷新的间隔，单位为秒，如值小于服务器设定的超时时间，连接可能会被强制关闭</summary>
        public static int PingInterval { get; } = 10;
        /// <summary>Ping延迟的时间</summary>
        public static int PingTimeout { get; } = 40;
        // --- --- ---

        // --- 字段 --- ---
        /// <summary>
        /// 连接主服务器的客户端
        /// </summary>
        [Obsolete("使用MainCliect类")]
        private static PolySocket m_MainSocket;

        /// <summary>提供对客户端的访问</summary>
        [Obsolete("直接新建字段")]
        public static ServiceProvider clientProvider;

        private static string playerName;
        // --- --- ---

        static PolyNetwork()
        {
            Debug.LogInfo($"PolyNetwork {VERSION}");

            //创建游戏物体PloyMono，以允许PolyNetwork的函数委托至Unity主线程中执行
            MonoHandle = MonoHandler.Create("PolyMono");
        }

        [Obsolete("直接新建字段")]
        private static void CreateClientProvider()
        {
            IServiceCollection services = new ServiceCollection();

            services.AddSingleton(new MainClient());

            clientProvider = services.BuildServiceProvider();
        }

        /// <summary>设置<see cref="PolySocket"/>的日志器</summary>
        public static PolySocket SetLogger(this PolySocket polySocket)
        {
            polySocket.SetLogger(Debug.Log, Debug.LogWarning, Debug.LogError);
            return polySocket;
        }

        /// <summary>将分发消息注册到Update，然后逐帧进行调用</summary>
        public static PolySocket RegisterToFireMessage(this PolySocket polySocket)
        {
            MonoHandle.OnUpdate += () => 
            {
                if (polySocket != null && polySocket.IsConnected)
                {
                    polySocket.FireMessage(MAX_MESSAGE_FIRE);
                }
            };
            return polySocket;
        }

        public static PolySocket RegisterToPingUpdate(this PolySocket polySocket)
        {
            MonoHandle.OnUpdate += () =>
            {
                if (polySocket.IsTimeout())
                {
                    polySocket.Close();
                    Debug.LogWarning("连接超时！服务器已关闭!");
                }
                else
                {
                    polySocket.RefreshPing();
                }
            };
            return polySocket;
        }

        /// <summary>创建一个 <see cref="PolySocket"/> 对象，
        /// 设置该 <see cref="PolySocket"/> 输出器并注册到
        /// <see cref="PolyNetwork"/> 的相关事件中</summary>
        internal static PolySocket CreateSocket()
        {
            return new PolySocket()
                .SetLogger() //设置Logger
                .RegisterToFireMessage() //添加分发消息的逐帧处理
                .RegisterToPingUpdate(); //添加处理ping相关的逐帧处理
        }

        

        /// <summary>连接回执</summary>
        [System.Obsolete("直接使用AsyncReport类")]
        public struct ConnectReport
        {
            public bool isSuccess;
            public string output;
        }
    } 
}